DeepFace:人脸识别库 DeepFace 简单认知

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》

写在前面


  • 工作中遇到,简单整理
  • 博文内容为 deepface 的简单介绍
  • 理解不足小伙伴帮忙指正

对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧 ——赫尔曼·黑塞《德米安》


人脸识别基本原理:

人脸检测:人脸检测是指在图像或视频中自动检测出人脸的位置,并将其框出来的过程。该技术通常使用分类器或神经网络模型来检测面部特征、形状、颜色等,从而确定人脸的位置。

人脸识别:人脸识别是指在已经检测到人脸的基础上,通过对其特征进行比较和匹配,将其与先前存储的一组人脸数据集中的个体进行识别和辨认的过程。这种技术通常使用各种算法(如 PCA、LBP、CNN 等)来提取人脸特征,并使用相似性计算方法来比较和匹配人脸。

DeepFace

DeepFace 是 Python 上最轻量级的人脸识别和面部属性分析库。开源的 DeepFace 库包括所有用于人脸识别的前沿 AI 模型,并自动处理后台面部识别的所有程序。

安装很方便,更过内容小伙伴可以参考项目文档,https://github.com/serengil/deepface

1
# pip install deepface==0.0.79

在识别时,需要下载对应模型的权重文件,有些是特征点获取的模型,需要科学上网,如果无法下载,可以到有网的机器下载,项目中的 单元测试中有一些测试脚本,执行的时候会下载,

支持的功能:

  • 人脸检测:人脸检测是指通过图片或者视频帧,通过检测算法,确定人脸的位置坐标
1
2
3
4
5
6
7
rst = DeepFace.extract_faces(
img_path=image,
target_size=(224, 224),
detector_backend="mtcnn",
enforce_detection=True,
align=True,
grayscale=False)
  • 人脸验证:人脸验证的任务是指将一张脸与另一张人脸进行比较,以验证它是否匹配。因此,人脸验证通常用于将候选人的面部与另一个候选人的面部进行比较。这可用于确认物理人脸是否与身份证件中的人脸匹配。
1
verification = DeepFace.verify(img1_path = "img1.jpg", img2_path = "img2.jpg")
  • 人脸识别:任务是指在图像数据库中查找人脸。执行人脸识别需要多次运行人脸验证。
1
recognition = DeepFace.find(img_path = "img.jpg", db_path = “C:/facial_db")
  • 面部属性分析:人脸属性分析的任务是指描述人脸图像的视觉属性。因此,面部属性分析用于提取年龄、性别分类、情绪分析或种族/民族预测等属性。
1
analysis = DeepFace.analyze(img_path = "img.jpg", actions = ["age", "gender", "emotion", "race"]) print(analysis)
  • 实时人脸分析:此功能包括使用网络摄像头的实时视频源测试人脸识别和面部属性分析。
1
DeepFace.stream(db_path = “C:/facial_db”)

人脸检测器

人脸检测和对齐是面部识别管道非常重要的阶段。谷歌表示,仅面部对齐就可以将面部识别准确率提高0.76%。这里的检测即指这图片中找到人脸的位置,对齐即把人脸通过类似透视变换的操作一样。 deepface 支持的检测器如下:

  • OpenCV: 与其他人脸检测器相比,OpenCV 是最轻量级的人脸检测器。流行的图像处理工具使用不基于深度学习技术的 haar-cascade 算法。这就是为什么它很快,但它的性能相对较低。为了使 OpenCV 正常工作,需要正面图像。此外,它的眼睛检测性能一般。这会导致对齐问题。请注意,DeepFace 中的默认检测器是 OpenCV。 使用 OpenCV 进行人脸检测
  • Dlib: 该检测器在后台使用 hog 算法。因此,与 OpenCV 类似,它不是基于深度学习的。尽管如此,它的检测和对齐分数相对较高。
  • SSD: SSD 代表 单次检测器;它是一种流行的基于深度学习的检测器。SSD 的性能可与 OpenCV 相媲美。但是,SSD 不支持面部特征点,并且依赖于 OpenCV 的眼睛检测模块来对齐。尽管其检测性能很高,但对准分数仅为平均水平。
  • MTCNN: MTCNN 这是一个基于深度学习的人脸检测器,它带有面部特征点。这就是为什么 MTCNN 的检测和对齐得分都很高的原因。但是,它比 OpenCV,SSD 和 Dlib 慢。 MTCNN 是一种多任务级联卷积神经网络的人脸检测算法,能够同时实现人脸检测、关键点定位和人脸对齐等功能。其对于大尺寸人脸的检测效果较好,并且相对于 RetinaFace 的模型规模较小。
  • RetinaFace: RetinaFace 被公认为最先进的基于深度学习的人脸检测模型。它在野外的表现具有挑战性。但是,它需要很高的计算能力。这就是为什么与其他人脸检测器相比,RetinaFace 是速度最慢的人脸检测器。RetinaFace 是一种基于卷积神经网络的人脸检测算法,具有高精度的特点。其在 WIDER FACE 和 COCO 数据集上的表现比 MTCNN 更好,尤其是对于小尺寸人脸的检测效果更佳
1
detectors = ["opencv", "ssd", "mtcnn", "dlib", "retinaface"]

应该使用哪种人脸检测器? 需要根据实际情况分析

  • 如果 高置信度,考虑使用 RetinaFace 或 MTCNN
  • 如果希望高速,清洗一部分没有人脸的照片,那么,可以使用 OpenCV 或 SSD

人脸识别模型

人脸识别模型,即通过对人脸库的数据进行特征提取,然后提取需要识别的图片的特征,两者通过计算生成一个相似度值,这个值的指定阈值内,即确定为同一个人。

  1. VGG-Face: VGG 代表 视觉几何组。VGG 神经网络(VGGNet)是基于深度卷积神经网络最常用的图像识别模型类型之一。VGG 人脸识别模型在流行的野外标记人脸 (LFW) 数据集上实现了 97.78% 的准确率。
  2. Facenet: 该模型由谷歌的研究人员开发。FaceNet 被认为是通过深度学习进行人脸检测和识别的最先进的模型。 FaceNet 的主要优点是其高效率和高性能,据报道,它在 LFW 数据集上达到了99.63%的准确率。
  3. OpenFace :这个人脸识别模型是由卡内基梅隆大学的研究人员建立的。因此,OpenFace 在很大程度上受到 FaceNet 项目的启发,但这更轻量级,其许可证类型更灵活,OpenFace 在 LFW 数据集上实现了93.80%的准确率。
  4. DeepFace: 这种人脸识别模型是由 Facebook 的研究人员开发的。Facebook DeepFace 算法是在属于 4000 万张面孔的标记数据集上进行训练的,这是发布时最大的面部数据集。该方法基于具有九层的深度神经网络。 Facebook 模型在 LFW 数据集基准测试上实现了97.35%(+/- 0.25%)的准确率。
  5. DeepID: DeepID 人脸验证算法基于深度学习进行人脸识别。它是首批使用卷积神经网络并在人脸识别任务上实现优于人类性能的模型之一。Deep-ID 是由香港中文大学的研究人员引入的。 基于 DeepID 人脸识别的系统是第一批在这项任务中超越人类表现的系统。例如,DeepID2 在野外标记面孔(LFW)数据集上实现了99.15%
  6. Dlib: Dlib 人脸识别模型将自己命名为“世界上最简单的 python 面部识别 API”。 Dlib 的人脸识别工具将人脸图像映射到 128 维矢量空间,其中同一个人的图像彼此靠近,而不同人的图像相距甚远。因此,dlib 通过将人脸映射到 128d 空间,然后检查它们的欧几里得距离是否足够小来执行人脸识别。 dlib 模型的距离阈值为 0.6,在标准 LFW 人脸识别基准上实现了 99.38% 的准确率。
  7. ArcFace: 这是模型组合中的最新型号。它的联合设计师是伦敦帝国理工学院和 InsightFace 的研究人员。ArcFace 模型在 LFW 数据集上的准确度达到 99.40%
  8. SFace: 是一种人脸识别的预训练模型,它是基于深度神经网络的人脸识别模型。SFace 模型是由中国科学院自动化研究所的研究人员开发的,它在多个人脸识别竞赛中表现出色。SFace 模型采用了一种名为“中心损失”的训练方法,可以使得模型在人脸识别任务中更加准确。
1
models=["VGG-Face", "Facenet", "Facenet512", "OpenFace", "DeepFace", "DeepID", "ArcFace", "Dlib","SFace"]

经过测试发现,Deepface 中,使用默认阈值,ArcFace,和 SFace 的识别度要好于其他的模型。当然,对应的阈值可以通过修改源码的方式调整,这里我们已 cosine 为例

对应的文件位置为:Python\Python310\site-packages\deepface\commons\distance.py,注释代码为默认的原来阈值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
......
def findThreshold(model_name, distance_metric):

base_threshold = {"cosine": 0.40, "euclidean": 0.55, "euclidean_l2": 0.75}

thresholds = {
"VGG-Face": {"cosine": 0.40, "euclidean": 0.60, "euclidean_l2": 0.86},
"Facenet": {"cosine": 0.40, "euclidean": 10, "euclidean_l2": 0.80},
"Facenet512": {"cosine": 0.30, "euclidean": 23.56, "euclidean_l2": 1.04},
# "ArcFace": {"cosine": 0.68, "euclidean": 4.15, "euclidean_l2": 1.13},
"ArcFace": {"cosine": 0.45, "euclidean": 4.15, "euclidean_l2": 1.13},
"Dlib": {"cosine": 0.07, "euclidean": 0.6, "euclidean_l2": 0.4},
# "SFace": {"cosine": 0.593, "euclidean": 10.734, "euclidean_l2": 1.055},
"SFace": {"cosine": 0.60, "euclidean": 10.734, "euclidean_l2": 1.055},
"OpenFace": {"cosine": 0.10, "euclidean": 0.55, "euclidean_l2": 0.55},
"DeepFace": {"cosine": 0.23, "euclidean": 64, "euclidean_l2": 0.64},
"DeepID": {"cosine": 0.015, "euclidean": 45, "euclidean_l2": 0.17},
}

threshold = thresholds.get(model_name, base_threshold).get(distance_metric, 0.4)

return threshold
.......

实际分析

在实际测试中发现,deepface 对 GPU 的利用很低,只是使用了显存,在同等情况下,还不如 CPU 并行跑的快。

实际使用中,如果采集的照片质量太低,考虑对识别数据进行清洗,然后在和人脸库比对,比如,检测人脸大小过滤,头部姿态过滤,置信度过滤等方式,同时可以调整阈值,这里需要说明的是,deepface 的 余弦相似度,和其他的人脸识别模型相反的,在取值时,用 1 减了,所以 deepface 的余弦值时越小越好,而且其他的人脸识别是越大越好。

可以做源码的这个位置看到

1
2
3
4
5
6
7
.......
def findCosineDistance(source_representation, test_representation):
a = np.matmul(np.transpose(source_representation), test_representation)
b = np.sum(np.multiply(source_representation, source_representation))
c = np.sum(np.multiply(test_representation, test_representation))
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
........

简单调用

1
2
3
4
5
6
7
8
9
10
from deepface import DeepFace

# 人脸识别
models=["VGG-Face", "Facenet", "Facenet512", "OpenFace", "DeepFace", "DeepID", "ArcFace", "Dlib"]
# 人脸检测
detectors = ["opencv", "ssd", "mtcnn", "dlib", "retinaface"]
# 教室人脸识别
verification = DeepFace.verify(img1_path = "hg1.png", img2_path = "hg2.png",model_name=models[6],detector_backend = detectors[4] )
print(verification)

这里之前测试,所以做了一个,deepface 环境镜像 ,涉及 deepface API 环境, deepface 部分 models(*.h5) 权重文件和检测器,环境有问题小伙伴可以直接用

1
docker pull liruilong/deepface_and_deepface_models

方法参数介绍

verify 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
"""
@Time : 2023/06/13 00:34:17
@Author : liruilonger@gmail.com
@Version : 1.0
@Desc : 人脸验证:用于验证图像对是否为同一人或不同人,验证函数将面部图像表示为向量,然后计算这些向量之间的相似度。
同一人图像的向量应具有更高的相似度(或更小的距离)比不同人的向量。

Args:
+ img1_path (str): 第一张图像的路径
+ img2_path (str): 第二张图像的路径
+ model_name (str): 要使用的人脸识别模型的名称(默认为“VGG-Face”)
+ detector_backend (str): 要使用的人脸检测后端(默认为“opencv”)
+ distance_metric (str): 用于比较面部嵌入的距离度量(默认为“cosine”)
+ enforce_detection (bool): 是否在图像中未检测到人脸时引发异常(默认为True)
+ align (bool): 是否在生成嵌入之前执行面部对齐(默认为True)
+ normalization (str): 用于预处理图像的归一化技术(默认为“base”)
Returns:
+ verified(核实):True
+ distance(距离):0.4439834803806296
+ threshold(阈值):0.593
+ model:SFace
+ detector_backend:mtcnn
+ similarity_metric(相似性指标):cosine
+ facial_areas(人脸位置):{'img1': {'x': 0, 'y': 0, 'w': 200, 'h': 255}, 'img2': {'x': 2, 'y': 13, 'w': 194, 'h': 231}}
+ time:1.95
void
"""

dfs = DeepFace.verify(
img1_path="W:\\python_code\\deepface\\temp\\cf\\cf_6dd3a0638cf4f4006aa1f455cac65577d.jpg.png",
img2_path ="W:\\python_code\\deepface\\temp\\cf\\cf_8a96787835b5d4677a56ad6db0c610958.jpg.png",
model_name="SFace",
detector_backend="mtcnn",
enforce_detection=False)

find 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"""
@Time : 2023/05/21 02:35:51
@Author : liruilonger@gmail.com
@Version : 1.0
@Desc : DeepFace.find方法是DeepFace库中的一个方法,用于在人脸数据库中查找与给定人脸最相似的人脸。
Args:
- img_path:要查找的人脸图像路径、numpy数组(BGR)或base64编码的图像。
- db_path:人脸数据库路径。您应该在此文件夹中存储一些.jpg文件。
- model_name:人脸识别模型的名称,例如VGG-Face、Facenet、Facenet512、OpenFace、DeepFace、DeepID、Dlib、ArcFace、SFace。
- distance_metric:距离度量方法可以是cosine、euclidean或euclideanl2。
- enforce_detection 参数是一个布尔值,指定如果无法检测到人脸,则该函数是否应引发异常。如果不想得到异常并仍要运行该函数,则将其设置为False。这对于低分辨率图像可能很方便。
- detector_backend 参数指定要使用的人脸检测器后端,可以是opencv、retinaface、mtcnn、ssd、dlib或mediapipe。
- align 参数是一个布尔值,指定是否应对人脸进行对齐。
- normalization 参数指定要使用的归一化方法,可以是base VGGFace Facenet raw 等
- silent参数是一个布尔值,用于禁用一些日志记录和进度条。
Returns:
df: 返回一个满足指定阈值的 的一个 pandas 对象
"""
dfs = DeepFace.find(
img_path="huge_1.jpg",
db_path="W:\python_code\db",
model_name="DeepID",
distance_metric="cosine",
enforce_detection=True,
detector_backend="retinaface",
align=False,
normalization="ArcFace",
silent=False,
)

extract_faces 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"""
@Time : 2023/05/20 03:50:07
@Author : liruilonger@gmail.com
@Version : 1.0
@Desc : extract_faces 用于对图像进行特征分析,提取头像坐标,
在实际使用中,如果对精度有要求,可以通过 `confidence` 来对提取的人脸进行过滤,
Args:
extract_faces方法接受以下参数:
- img_path:要从中提取人脸的图像路径、numpy数组(BGR)或base64编码的图像。
- target_size:人脸图像的最终形状。将添加黑色像素以调整图像大小。
- detector_backend:人脸检测后端可以是 retinaface、mtcnn、opencv、ssd或dlib。
- enforce_detection:如果在提供的图像中无法检测到人脸,则该函数会引发异常。如果不想得到异常并仍要运行该函数,则将其设置为False。
- align:根据眼睛位置对齐。
- grayscale:以RGB或灰度提取人脸。

Returns:
返回一个包含人脸图像、人脸区域和置信度的字典列表。其中,
- face 键对应的值是提取的人脸图像
- facial_area 键对应的值是人脸在原始图像中的位置和大小
- confidence 键对应的值是人脸检测的置信度

"""
rst = DeepFace.extract_faces(
img_path=image,
target_size=(224, 224),
detector_backend="mtcnn",
enforce_detection=True,
align=True,
grayscale=False)

analyze 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"""
@Time : 2023/05/31 01:44:27
@Author : liruilonger@gmail.com
@Version : 1.0
@Desc : analyze 方法是 DeepFace 库中的一个函数,用于分析人脸属性,包括年龄、性别、情绪和种族。
在后台,分析函数构建卷积神经网络模型,以对输入图像中的人脸进行年龄、性别、情绪和种族分类。
Args:
- img_path:图像路径、numpy 数组(BGR)或 base64 编码的图像。如果源图像中有多个人脸,则结果将是出现在图像中的人脸数量大小的列表。
- actions: 参数是一个元组,其中默认值为 ('age', 'gender', 'emotion', 'race'),您可以删除其中的一些属性。
- enforce_detection :参数默认为 True,如果未检测到人脸,则函数会抛出异常。如果您不想得到异常,则可以将其设置为 False。这对于低分辨率图像可能很方便。
- detector_backend: 参数指定要使用的人脸检测器的后端,例如 OpenCV、RetinaFace、MTCNN 等。
- align: 参数是一个布尔值,表示是否根据眼睛位置进行对齐。
- silent :参数是一个布尔值,表示是否禁用(某些)日志消息。
Returns:
- "region":表示人脸在图像中的位置和大小。
- "age":表示人脸的年龄。
- "dominant_gender":表示人脸的主要性别。
- "gender":表示人脸的性别及其置信度。
- "dominant_emotion":表示人脸的主要情绪。
- "emotion":表示人脸的情绪及其置信度。
- "dominant_race":表示人脸的主要种族。
- "race":表示人脸的种族及其置信度。
"""
dfs = DeepFace.analyze("database\yz_W.jpg",detector_backend="retinaface")

不同识别模型测试的简单统计:

识别流程:

  1. 通过 检测模型 retinaface 模型获取所有的人脸: 选择原因:小尺寸人脸的检测效果更佳,对人脸进行切片
  2. 过滤置信度大于 0.99 的人脸,这里的置信度即为人脸可信度,由 retinaface 给出,同时对切片大小过滤,太小的直接舍弃
  3. 通过 opencv 和 Dlib 获取特征点和头部姿态,这里实际上又进行了一次检测,使用 Dlib 库 检测,过滤头部姿态欧拉角小于 15 度的数据
  4. 过滤出的数据通过 DeepFace.find 方法进行人脸库比对,这里对人脸又进行了一次检测,使用检测模型 mtcnn,使用识别模型为下面的变量

相同人脸库数据,相同识别数据集,不同识别模型统计:

模型名称 识别结果数 识别陌生人 识别总人数 识别错误 识别成功 识别成功率
VGG-Face
Facenet 430 267 163 118 45 27%
Facenet512 432 311 121 57 64 52%
OpenFace 434 3 431 3 0 0%
DeepFace 430 267 163 125 38 23%
Dlib 428 173 255 174 81 31%
ArcFace 430 255 175 62 113 65%
SFace 432 346 86 7 79 91%

测试发现,当前的数据集,SFace 相对来说要好一点,整体上还是达不到期望。 主要是图片质量问题,当前检测识别属于小目标检测识别,如果是打卡或者门禁其他的大目标正脸识别,是OK的。

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦 :)


https://viso.ai/computer-vision/deepface/

https://github.com/serengil/deepface


© 2018-2023 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

发布于

2023-05-04

更新于

2023-06-21

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×